package com.gt.quality.system.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gt.quality.base.BaseCommonController;
import com.gt.quality.base.BaseCommonService;
import com.gt.quality.system.entity.mock.MockInfo;
import com.gt.quality.system.entity.vo.MockInfoRequest;
import com.gt.quality.base.pojo.Resp;
import com.gt.quality.system.service.mock.MockService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * Mock接口
 * @author makeJava
 */
@RestController
@RequestMapping("mock")
@Tag(name = "定义模拟请求-响应接口")
@Slf4j
@SaIgnore
public class MockServiceController extends BaseCommonController<MockInfo> {

    /**
     * Description: 使用 Spring Framework 的事件发布机制发布应用程序事件。
     */


    private MockService mockService;

    @Value("${mock.path.starts.with:/qa/mock/api}")
    private String pathStartsWith;


    @Autowired
    public void setMockService(MockService mockService) {
        this.mockService = mockService;
    }


    @PostMapping("/addMockInfo")
    @Operation(summary = "添加Mock信息")
    public Resp<Object> addMockInfo(@RequestBody MockInfoRequest body) {
        String interfaceRouter = body.getInterfaceRouter();
        if (StringUtils.isBlank(interfaceRouter) || !interfaceRouter.startsWith(pathStartsWith)) {
            return Resp.error("Mock添加接口前缀必须是" + pathStartsWith);
        }
        MockInfo mockInfo = body.buildMockInfo(body);
        if (mockInfo.getMockId() == null) {
            mockService.save(mockInfo);
        } else {
            mockService.updateById(mockInfo);
        }
        return Resp.ok("url加载Mock成功" + body.getInterfaceRouter());
    }

    /**
     * 万能模拟接口
     *
     * @return Resp
     */
    @RequestMapping(value = "/api/**", method = {RequestMethod.GET, RequestMethod.POST})
    @Operation(summary = "Mock万能模拟接口")
    @SaIgnore
    public Resp<Object> addMockInfoByRequest(HttpServletRequest request) {
        String requestUrl = request.getRequestURI();
        LambdaQueryWrapper<MockInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MockInfo::getInterfaceRouter, requestUrl);
        List<MockInfo> list = mockService.list(queryWrapper);
        if (list == null) {
            return Resp.error("Mock动态回调Request 没找到报文");
        }
        MockInfo mockInfo = list.get(0);
        // 开启阻塞延时
        if (mockInfo.isEnableBlockedTime()) {
            try {
                log.info("延迟----响应---启动");
                long timeOut = mockInfo.getBlockedTime();
                Thread.sleep(timeOut);
            } catch (InterruptedException e) {
                log.error("接口睡眠--->出错了{}", e.getMessage(), e);
                // 重新设置线程的中断状态
                Thread.currentThread().interrupt();
                return Resp.error("接口延迟过程中被中断");
            }
        }
        if (mockInfo.isEnableHeaderCheck()) {
            String checkedHeader = mockInfo.getCheckedHeader();
            JSONObject entries = JSONUtil.parseObj(checkedHeader);
            for (Map.Entry<String, Object> entry : entries.entrySet()) {
                String key = entry.getKey();
                String header = request.getHeader(key);
                if (StringUtils.isBlank(header) || !StringUtils.equals(header, entry.getValue().toString())) {
                    return Resp.error("Mock接口Header校验不过");
                }
            }
        }
        String responseBody = mockInfo.getResponseBody();
        if (responseBody.startsWith("{") && responseBody.endsWith("}")) {
            return Resp.ok(JSONUtil.parseObj(responseBody));
        }
        return Resp.ok(mockInfo.getResponseBody());

    }


    @Override
    public BaseCommonService<MockInfo> getThisService() {
        return mockService;
    }

    @Override
    protected boolean isSuperExcel() {
        return false;
    }
}
